﻿namespace FluentMvc
{
    using System;
    using System.Collections.Generic;
    using System.Linq.Expressions;
    using System.Web.Mvc;

    public class RangeRulesConfiguration<TModel, TProperty, TChild> : RuleConfigurator<TModel, TProperty, TChild>
        where TModel : class
        where TChild : RuleConfigurator<TModel, TProperty, TChild>
    {
        public RangeRulesConfiguration(Expression<Func<TModel, TProperty>> selector, ModelContext<TModel> context)
            : base(selector, context)
        {
        }

        public TChild Min(TProperty min, Action<RuleInitializer<TModel, TProperty>> configuration = null)
        {
            var validationRule = new ModelClientValidationRule {ValidationType = "required"};
            validationRule.ValidationParameters.Add("min", min);
            var rule = new ValidationSetting<TModel>
            {
                CustomValidation = model => Comparer<TProperty>.Default.Compare(PropertySelector(model), min) >= 0,
                PropertyName = PropertyName,
                ClientValidationRules = new List<ModelClientValidationRule>{validationRule}
            };
            ModelContext.GetSettings(PropertyName).ValidationSettings.Add(RunConfiguration(configuration, rule));
            return Child;
        }

        public TChild Max(TProperty max, Action<RuleInitializer<TModel, TProperty>> configuration = null)
        {
            var validationRule = new ModelClientValidationRule { ValidationType = "required" };
            validationRule.ValidationParameters.Add("max", max);
            var rule = new ValidationSetting<TModel>
            {
                CustomValidation = model => Comparer<TProperty>.Default.Compare(PropertySelector(model), max) <= 0,
                PropertyName = PropertyName,
                ClientValidationRules = new List<ModelClientValidationRule>{validationRule}
            };
            ModelContext.GetSettings(PropertyName).ValidationSettings.Add(RunConfiguration(configuration, rule));
            return Child;
        }

        public TChild Range(TProperty min, TProperty max, Action<RuleInitializer<TModel, TProperty>> configuration = null)
        {
            var validationRule = new ModelClientValidationRule {ValidationType = "range"};
            validationRule.ValidationParameters.Add("min", min);
            validationRule.ValidationParameters.Add("max", max);
            var rule = new ValidationSetting<TModel>
                           {
                               CustomValidation = model =>
                                                  {
                                                      if (Comparer<TProperty>.Default.Compare(PropertySelector(model), min) < 0)
                                                          return false;
                                                      if (Comparer<TProperty>.Default.Compare(PropertySelector(model), max) > 0)
                                                          return false;
                                                      return true;
                                                  },
                               PropertyName = PropertyName,
                               ClientValidationRules = new List<ModelClientValidationRule>{validationRule}
                           };
            ModelContext.GetSettings(PropertyName).ValidationSettings.Add(RunConfiguration(configuration, rule));
            return Child;
        }
    }
}